package org.opentcs.kcvehicle.communication.kc.syn;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * （重点）.
 * AsyncFuture 这个类就是票据， 刚拿到这个票据是没有信息的，当done == true 的时候，这个票据 上就自动有信息了.
 * 这个结果类设计的比较神奇.
 */
public class AsyncFuture<Object>
    implements
      Future<Object> {

  private static final Logger logger = LoggerFactory.getLogger(AsyncFuture.class);
  private volatile boolean done = false;
  private Object oldRequest;
  private Object result;

  public AsyncFuture(Object oldRequest) {
    this.oldRequest = oldRequest;
  }

  public AsyncFuture() {
  }

  public void done(Object result) {
    synchronized (this) {
      this.result = result;
      this.done = true;
      //注意这里的notifyAll只能唤醒 本锁的所有 下的所有 wait(),这里的锁就是 AsyncFuture这个类
      notifyAll();
    }
  }


  @Override
  public Object get(Long timeout)
      throws Exception {
    return null;
  }

  @Override
  public Object get(Long timeout, String transationId)
      throws Exception {
    synchronized (this) {
      //其实有 synchronize就相当于有一个阻塞队列，当有线程执行了wait 方法，就会把执行wait的这个线程给加入wait<Thread> 队列，
      //当有线程执行notify方法的时候，就会往这个队列中取出一个或者多个Thread,取出来以后就能执行后续代码了
//            System.out.println("get");

      // 当线程执行wait()时，会把当前的锁释放，然后让出CPU，进入等待状态。 wait()会立刻释放synchronized（obj）中的obj锁，以便其他线程可以执行obj.notify()
      // * 当线程执行notify()/notifyAll()方法时，会唤醒一个处于等待状态该对象锁的线程，然后继续往下执行，直到执行完退出对象锁锁住的区域（synchronized修饰的代码块）后再释放锁
      this.wait(timeout);
      if (!done) {
        //logger.error("T3 timeout , request information: "+oldRequest.toString());
        SendedList.remove(transationId);
        throw new Exception("T3 timeout , request information: " + oldRequest.toString());
      }

      //因为上面的代码是加锁的，所以这里的代码也是加锁的。
      return result;
    }

  }
}
